package cn.kent;

import cn.kent.util.Employee;
import cn.kent.util.EmployeeData;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 测试 Stream的终止操作
 * 1. 查找和匹配
 * 2. 归约
 * 3. 收集
 */
public class StreamAPITest2 {
    @Test
    public void test() {
        final List<Employee> employees = EmployeeData.getEmployees();
        final boolean b = employees.stream().allMatch(e -> e.getSalary() > 1500);
        System.out.println("所有员工的薪水是否均大于1500 -> " + b);

        final boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() > 1500);
        System.out.println("是否包含有一个人薪水大于1500" + anyMatch);

        final boolean noneMatch = employees.stream().noneMatch(e -> e.getName().equals("马云"));
        System.out.println("是否没有一个人姓名为 马云 -> " + noneMatch);

        final Optional<Employee> first = employees.stream().findFirst();
        System.out.println("第一个元素为： " + first);

        // 使用并行流，将会返回任一个中的第一个，如果使用串行流，那么始终都是一个流中的第一个。
        final Optional<Employee> any = employees.parallelStream().findAny();
        System.out.println("并行流中的任意一个 -> " + any);

        final long count = employees.stream().filter(e -> e.getSalary() > 1500).count();
        System.out.println("工资大于1500的总共有几个人 -> " + count);

        // 基础写法
//        final Optional<Employee> max = employees.stream().max(new Comparator<Employee>() {
//            @Override
//            public int compare(Employee o1, Employee o2) {
//                return Integer.compare(o1.getSalary(), o2.getSalary());
//            }
//        });
        // lambda表达式写法
        final Optional<Employee> max = employees.stream().max(
                (o1, o2) -> Integer.compare(o1.getSalary(), o2.getSalary()));
        // map写法，得到最高的薪资数，没有拿到该用户的所有信息 -> 返回流中的最大值
        final Optional<Integer> max1 = employees.stream().map(Employee::getSalary).max(Double::compare);
        System.out.println("工资最高的人是->" + max);
        System.out.println("工资最大值是->" + max1);

        final Optional<Integer> min = employees.stream().map(Employee::getSalary).min(Double::compare);
        System.out.println("工资最小值是->" + min);
        final Optional<Employee> min1 = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println("工资最低的人->" + min1);

        System.out.println();

        System.out.println("流内部迭代");
        employees.stream().forEach(System.out::println);

        System.out.println("使用集合的遍历操作:");
        employees.forEach(System.out::println);
    }

    /**
     * 归约
     * reduce: 可以将流中元素反复结合起来，得到一个值，返回
     */
    @Test
    public void test2() {
        // 计算1-10的自然数的和
        final List<Integer> list = Arrays.asList(1, 2, 4, 5, 6, 7, 8, 9, 10);
        final Integer sum = list.stream().reduce(0, Integer::sum);
        System.out.println(sum);


        // 计算公司中员工工资总和
        final List<Employee> employees = EmployeeData.getEmployees();
        final Stream<Integer> salaryStream = employees.stream().map(Employee::getSalary);
//        final Optional<Integer> sumMoney = salaryStream.reduce(Integer::sum);
        final Optional<Integer> sumMoney = salaryStream.reduce((d1, d2) -> d1 + d2);
        System.out.println(sumMoney);
    }

    /**
     * 收集collect
     * 将流转换为其他形式，接收一个Collector接口的实现，用于给Stream中元素做汇总的方法
     */
    @Test
    public void test3(){
        final List<Employee> employees = EmployeeData.getEmployees();
        final List<Employee> employeeList = employees.stream().filter(e -> e.getSalary() > 1500).collect(Collectors.toList());
        employeeList.forEach(System.out::println);


        final Set<Employee> employeeSet = employees.stream().filter(e -> e.getSalary() > 1500).collect(Collectors.toSet());
        employeeSet.forEach(System.out::println);

    }
}
